<?php
use Ifsnop\Mysqldump as IMysqldump;
//添加定时任务周期
function cos_add_schedules($schedules) {
	$schedules['weekly'] = array(
		'interval' => 604800,
		'display' => '每周一次',
	);
	$schedules['monthly'] = array(
		'interval' => 2592000,
		'display' => '每月一次',
	);
	return $schedules;
}
add_filter('cron_schedules', 'cos_add_schedules', 10, 1);

//删除任务
function cos_delete_cron() {
	if(wp_next_scheduled('wp_cos')) {
		wp_clear_scheduled_hook('wp_cos');
	}
}

//任务挂接函数
function cos_cron_fun() {
	$error = cos_backup_mysql();
	if($error->get_error_message('error')) {
		$msg = $error->get_error_message('error');
	} else {
		$msg = '备份数据库成功：<br>&nbsp;&nbsp;&nbsp;&nbsp;时间：' . wp_date('Y年n月j日 H:i:s') . '<br>&nbsp;&nbsp;&nbsp;&nbsp;文件：' . $error->get_error_message('info');
	}

	cos_mail($msg, '定时备份通知');
}
add_action('wp_cos', 'cos_cron_fun');

//发送邮件
function cos_mail($msg='', $title='') {
	$blogname = get_bloginfo('name');
	$adminemail = get_bloginfo('admin_email');
	if(!$title) {
		$title = '备份通知';
	}
	$title = $blogname . ' - ' . $title;
	$headers = array('Content-Type: text/html; charset=UTF-8');
	wp_mail($blogname . ' <' . $adminemail . '>', $title, $msg, $headers);
}

//备份数据库
function cos_backup_mysql() {
	$error = new WP_Error;
	$WPCOS = new WPCOS('backup');
	if(!$WPCOS->options || !$WPCOS->options['bucket_backup']) {
		$error->add('error', '还没有配置API信息');
		return $error;
	}

	if(function_exists('set_time_limit')) {
		set_time_limit(600);
	}

	$suffix = wp_date('j');
	$temp = tempnam(sys_get_temp_dir(), 'db_');
	try {
		$dump = new IMysqldump\Mysqldump('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASSWORD);
		$dump->start($temp);
	} catch (\Exception $e) {
		$error->add('error', $e->getMessage());
	}
	if(!$error->has_errors()) {
		//打包文件
		$size = filesize($temp);
		$handle = fopen($temp, 'rb');
		$sql = fread($handle, $size);
		fclose($handle);
		unlink($temp);

		$file = tempnam(sys_get_temp_dir(), 'db_') . '.zip';
		$zip = new ZipArchive;
		if($zip->open($file, ZIPARCHIVE::CREATE ) === TRUE) {
			$zip->addFromString(DB_NAME . '.sql', $sql);
			$zip->close();
		}

		//上传到云存储
		$domain = parse_url(get_option('siteurl'));
		$domain = $domain['host'];
		$target = $domain . '_' . DB_NAME . '_' . $suffix . '.zip';

		$upload = $WPCOS->upload($target, $file);
		if($upload !== true) {
			$error->add('error', $upload);
		} else {
			$error->add('info', $target);
		}
		unlink($file);
	}

	return $error;
}

//获取所有附件ID
function cos_get_attachment_ids() {
	global $wpdb;
	$ids = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_type='attachment'");
	return $ids;
}

//获取缩略图
function cos_images($meta) {
	if(!$meta) {
		return [];
	}

	$upload_path = get_option('upload_path');
	$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';

	if(empty($meta['sizes'])) {
		return [$upload_path . '/' . $meta['file']];
	}

	$images[] = $upload_path . '/' . $meta['file'];

	$path = dirname($meta['file']);
	$path = $path == '.' ? '' : '/' . $path;
	foreach($meta['sizes'] as $size) {
		if(!$size['file']) continue;
		$images[] = $upload_path . $path . '/' . $size['file'];
	}
	$images = array_unique($images);
	return $images;
}

//初始化同步
function cos_initialize_sync($attachments) {
	$WPCOS = new WPCOS('upload');
	if(!$WPCOS->options || !$WPCOS->options['bucket_upload']) {
		return '还没有配置API信息';
	}
	$error = new WP_Error;

	foreach($attachments as $attachment) {
		if(wp_attachment_is_image($attachment)) {
			$meta = wp_get_attachment_metadata($attachment);
			$images = cos_images($meta);
			foreach($images as $image) {
				if(!$image) continue;
				$target = '/' . $image;
				$file = ABSPATH . $image;
				$upload = $WPCOS->upload($target, $file);
				if($upload === true) {
					if('off' != $WPCOS->options['watermark']) {
						$WPCOS->image_processing($target, 'watermark');
					}
				} else {
					$error->add('error', $upload . '：' . $target);
				}
			}
		} else {
			$file = get_attached_file($attachment);
			$target = '/' . str_replace(ABSPATH, '', $file);
			$upload = $WPCOS->upload($target, $file);
			if($upload !== true) {
				$error->add('error', $upload . '：' . $target);
			}
		}
	}

	if($error->has_errors()) {
		$msg = '初始同步上传错误报告：<br><br>';
		$msg .= join('<br>', $error->get_error_messages('error'));
	} else {
		$msg = '初始同步已完成，全部附件已上传至腾讯COS。';
	}

	cos_mail($msg, '初始同步报告');

	return $msg;
}

//处理上传的文件
function cos_upload_file($return, $file, $new_file, $type) {
	$options = get_option('wp_cos');
	$options = unserialize($options);
	if(!$options || !$options['bucket_upload']) return null;
	
	//不保留本地附件时处理
	if('no' == $options['local_attachment']) {
		$upload_path = get_option('upload_path');
		$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';
		$upload_path = ABSPATH . $upload_path . '/';

		$tmp_file = str_replace($upload_path, '', $new_file);

		$tmp_dir = dirname($tmp_file);
		$tmp_dir = $tmp_dir == '.' ? '' : '/' . $tmp_dir;
		$tmp_dir = sys_get_temp_dir() . $tmp_dir;
		if(!is_dir($tmp_dir)) {
			wp_mkdir_p($tmp_dir);
		}

		$tmp_file = $tmp_dir . '/' . basename($tmp_file);
		$_SESSION['cos_handle_upload'] = $tmp_file;

		@copy($file['tmp_name'], $tmp_file);
		$stat  = stat(dirname($tmp_file));
		$perms = $stat['mode'] & 0000666;
		chmod($tmp_file, $perms);
		unlink($file['tmp_name']);
		return true;
	}

	return null;
}
add_action('pre_move_uploaded_file', 'cos_upload_file', 10, 4);

//修改上传信息
function cos_handle_upload($file) {
	if(isset($_SESSION['cos_handle_upload'])) {
		$file['file'] = $_SESSION['cos_handle_upload'];
		unset($_SESSION['cos_handle_upload']);
	}
	return $file;
}
add_action('wp_handle_upload', 'cos_handle_upload', 10, 1);

//过滤上传路径
function cos_relative_upload_path($new_path, $path) {
	$options = get_option('wp_cos');
	$options = unserialize($options);
	if(!$options || !$options['bucket_upload']) return $new_path;

	if('no' == $options['local_attachment']) {
		return str_replace(sys_get_temp_dir() . '/', '', $path);
	}

	return $new_path;
}
add_filter('_wp_relative_upload_path', 'cos_relative_upload_path', 10, 2);

//附件名称重复检测
function cos_unique_filename($filename, $ext, $dir) {
	global $wpdb;
	$upload_path = get_option('upload_path');
	$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';
	$upload_path = ABSPATH . $upload_path . '/';
	$subdir = str_replace($upload_path, '', $dir);

	$name = wp_basename($filename, $ext);
	$where = $subdir . '/' . $name . '.';
	$num = 0;
	while($wpdb->get_var("SELECT COUNT(meta_id) FROM $wpdb->postmeta WHERE meta_key='_wp_attached_file' AND meta_value LIKE '{$where}%'")) {
		$num++;
		$new_name = $name . '-' . $num;
		$where = $subdir . '/' . $new_name . '.';
		$filename = $new_name . $ext;
	}
	return $filename;
}
add_filter('wp_unique_filename', 'cos_unique_filename', 10, 3);

//上传文件时同步
function cos_generate_metadata($meta, $attachment_id) {
	global $wpdb;
	$WPCOS = new WPCOS('upload');
	if(!$WPCOS->options || !$WPCOS->options['bucket_upload'] || empty($meta['file'])) {
		return $meta;
	}
	$upload_path = get_option('upload_path');
	$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';
	$delet_attachment = 'no' == $WPCOS->options['local_attachment'];

	if($delet_attachment) { 
		$root_path = sys_get_temp_dir();
	} else {
		$root_path = ABSPATH . $upload_path;
	}

	$subdir = dirname($meta['file']);
	$subdir = $subdir == '.' ? '' : '/' . $subdir;

	$tmp_file = $root_path . '/' . $meta['file'];

	$failure = [];
	//上传图片
	if(wp_attachment_is_image($attachment_id)) {
		$target = '/' . $upload_path . '/'. $meta['file'];
		$is_image_processing = $WPCOS->is_image_processing($tmp_file);
		//上传原图
		$upload = $WPCOS->upload($target, $tmp_file);
		if($upload === true) {
			if($is_image_processing) {
				$processing = $WPCOS->image_processing($target);
				if($processing) {
					$meta['width'] = $processing['width'];
					$meta['height'] = $processing['height'];

					if(isset($processing['new'])) {
						$meta['file'] = str_replace($processing['old'], $processing['new'], $meta['file']);
						$guid = get_post_field('guid', $attachment_id);
						$guid = str_replace($processing['old'], $processing['new'], $guid);
						$wpdb->update($wpdb->posts, [
							'guid' => $guid,
							'post_mime_type' => $processing['mime']
						], [
							'ID' => $attachment_id
						],['%s', '%s'], '%d');

						update_post_meta($attachment_id, '_wp_attached_file', $meta['file']);
						wp_cache_delete($attachment_id, 'posts');

						$tmp_file_new = str_replace($processing['old'], $processing['new'], $tmp_file);
						rename($tmp_file, $tmp_file_new);
						$tmp_file = $tmp_file_new;
					}

					if(!$delet_attachment) {
						$filec = $WPCOS->get_object('/' . $upload_path . $subdir . '/'. $processing['new']);
						if($filec) {
							file_put_contents($tmp_file, $filec);
						}
					}
				}
			}
		} else {
			$failure[] = $upload . '：' . $target;
		}

		//上传缩略图
		if(!empty($meta['sizes'])) {
			foreach($meta['sizes'] as $key=>$size) {
				if(!$size['file']) continue;
				$image = $root_path . $subdir . '/' . $size['file'];
				$target = '/' . $upload_path . $subdir . '/'. $size['file'];
				$upload = $WPCOS->upload($target, $image);
				if($upload === true) {
					if($is_image_processing) {
						$processing = $WPCOS->image_processing($target);
						if($processing) {
							$meta['sizes'][$key]['width'] = $processing['width'];
							$meta['sizes'][$key]['height'] = $processing['height'];

							if(isset($processing['new'])) {
								$meta['sizes'][$key]['file'] = $processing['new'];
								$meta['sizes'][$key]['mime-type'] = $processing['mime'];
								$image_new = str_replace($processing['old'], $processing['new'], $image);
								rename($image, $image_new);
								$image = $image_new;
							}

							if(!$delet_attachment) {
								$filec = $WPCOS->get_object('/' . $upload_path . $subdir . '/'. $processing['new']);
								if($filec) {
									file_put_contents($image, $filec);	
								}
							}
						}
					}
				} else {
					$failure[] = $upload . '：' . $target;
				}

				if($delet_attachment) {
					unlink($image);
				}
			}
		}
	} else {
		//上传其他附件
		$target = '/' . $upload_path . '/'. $meta['file'];
		$upload = $WPCOS->upload($target, $tmp_file);
		if($upload !== true) {
			$failure[] = $upload . '：' . $target;
		}
	}

	if($delet_attachment) {
		unlink($tmp_file);
	}
	
	if($failure) {
		cos_mail('同步文件，错误报告如下：<br>' . join('<br>', $failure), '同步文件失败');
	}

	return $meta;
}
add_filter('wp_generate_attachment_metadata', 'cos_generate_metadata', 10, 2);

//编辑图片同步
function cos_save_image_editor_file($return, $filename) {
	$WPCOS = new WPCOS('upload');
	if(!$WPCOS->options || !$WPCOS->options['bucket_upload']) {
		return null;
	}

	$target = '/' . str_replace(ABSPATH, '', $filename) . '/' . basename($filename);
	$upload = $WPCOS->upload($target, $filename);
	if($upload !== true) {
		cos_mail('同步编辑后的图片失败，文件：<br>' . $target, '同步编辑后的图片失败');
	}

	return null;
}
add_filter('wp_save_image_editor_file', 'cos_save_image_editor_file', 10, 2);

//同步删除
function cos_delete_attachment($attachment_id) {
	$WPCOS = new WPCOS('upload');
	if(!$WPCOS->options || !$WPCOS->options['bucket_upload']) {
		return;
	}

	if(wp_attachment_is_image($attachment_id)) {
		$meta = wp_get_attachment_metadata($attachment_id);
		$backup_sizes = get_post_meta($attachment_id, '_wp_attachment_backup_sizes', true);
		if($backup_sizes) {
			$meta['sizes'] = wp_parse_args($meta['sizes'], $backup_sizes);
		}
		$images = cos_images($meta);
		foreach($images as $image) {
			if(!$image) continue;
			$WPCOS->delete('/' . $image);
		}
	} else {
		$upload_path = get_option('upload_path');
		$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';
		$upload_path = ABSPATH . $upload_path;
		$file = get_attached_file($attachment_id);
		$file = str_replace($upload_path, '', $file);
		$WPCOS->delete($file);
	}
}
add_action('delete_attachment', 'cos_delete_attachment', 10, 1);

//替换内容中URL
function cos_the_content($content) {
	if(!is_singular() || !is_main_query()) return $content;
	$options = get_option('wp_cos');
	$options = unserialize($options);
	if(!$options || !$options['domain']) {
		return $content;
	}

	$upload_path = get_option('upload_path');
	$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';

	$localurl = get_option('siteurl') . '/' . $upload_path;
	$localurl = preg_quote($localurl, '/');
	$cdn_url = $options['domain'] . '/' . $upload_path;

	$content = preg_replace('/(<.*?["|\'])' . $localurl . '(.*?["|\'].*?>)/i', "$1$cdn_url$2", $content);
	return $content;
}
add_filter('the_content', 'cos_the_content', 10, 1);

//替换附件URL
function cos_attachment_url($url) {
	$options = get_option('wp_cos');
	$options = unserialize($options);
	if(!$options || !$options['domain']) {
		return $url;
	}

	if(is_admin() && 'no' !== $options['local_attachment']) {
		return $url;
	}

	$upload_path = get_option('upload_path');
	$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';

	$localurl = get_option('siteurl') . '/' . $upload_path;
	$cdn_url = $options['domain'] . '/' . $upload_path;

	$url = str_replace($localurl, $cdn_url, $url);
	return $url;
}
add_filter('wp_get_attachment_url', 'cos_attachment_url', 10, 1);

//编辑文章时替换URL
function cos_edit_pre($content) {
	$options = get_option('wp_cos');
	$options = unserialize($options);
	if(!$options || !$options['domain']) {
		return $content;
	}

	if('no' !== $options['local_attachment']) {
		return $content;
	}

	$upload_path = get_option('upload_path');
	$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';

	$localurl = get_option('siteurl') . '/' . $upload_path;
	$localurl = preg_quote($localurl, '/');
	$cdn_url = $options['domain'] . '/' . $upload_path;

	$content = preg_replace('/(<.*?["|\'])' . $localurl . '(.*?["|\'].*?>)/i', "$1$cdn_url$2", $content);
	return $content;
}
add_filter('content_edit_pre', 'cos_edit_pre', 10, 1);

//保存文章时替换URL
function cos_content_save($content) {
	$options = get_option('wp_cos');
	$options = unserialize($options);
	if(!$options || !$options['domain']) {
		return $content;
	}

	if('no' !== $options['local_attachment']) {
		return $content;
	}

	$upload_path = get_option('upload_path');
	$upload_path = $upload_path ? trim($upload_path, '/') : 'wp-content/uploads';

	$localurl = get_option('siteurl') . '/' . $upload_path;
	$cdn_url = $options['domain'] . '/' . $upload_path;
	$cdn_url = preg_quote($cdn_url, '/');

	$content = preg_replace('/(<.*?["|\'])' . $cdn_url . '(.*?["|\'].*?>)/i', "$1$localurl$2", $content);
	return $content;
}
add_filter('content_save_pre', 'cos_content_save', 10, 1);

//替换主题静态资源
function cos_loader_src($src) {
	if(is_admin()) return $src;
	$options = get_option('wp_cos');
	$options = unserialize($options);
	if(!$options || !$options['domain'] || 'site' != $options['cdn_target']) {
		return $src;
	}

	$localurl = get_option('siteurl');
	$cdn_url = $options['domain'];

	$src = str_replace($localurl, $cdn_url, $src);
	if(strpos($src, 'ver=')) {
        $src = remove_query_arg('ver', $src);
    }
    if(strpos($src, 'x54532')) {
        $src = remove_query_arg('x54532', $src);
    }
	return $src;
}
add_filter('style_loader_src', 'cos_loader_src', 10, 1);
add_filter('script_loader_src', 'cos_loader_src', 10, 1);
//add_filter('stylesheet_directory_uri', 'cos_loader_src', 10, 1);
//add_filter('theme_file_uri', 'cos_loader_src', 10, 1);
add_filter('theme_root_uri', 'cos_loader_src', 10, 1);

//Gravatar头像加速
function cos_rewrite_rules($wp_rewrite) {
	$new_rules = array(
		'gravatar\/([^\/]+)$' => 'index.php?pagename=gravatar&gravatar=$matches[1]'
	);
	$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'cos_rewrite_rules', 10, 1);

function cos_add_query_vars($query_vars) {
	$query_vars[] = 'gravatar';
	return $query_vars;
}
add_action('query_vars', 'cos_add_query_vars', 10, 1);

function cos_cdn_gravatar($query) {
	if(!isset($query->query_vars['pagename']) || $query->query_vars['pagename'] != 'gravatar') {
		return;
	}
	//$gravatar = 'https://secure.gravatar.com/avatar/';
	$gravatar = 'https://cravatar.cn/avatar/';
	$gravatar .= $query->query_vars['gravatar'];
	if(isset($query->query_vars['s'])) {
		$gravatar .= '?s=' . $query->query_vars['s'];
	}
	wp_redirect($gravatar, 302);
    exit;
}
add_action('parse_request', 'cos_cdn_gravatar', 10 , 1);

function cos_get_avatar_url($url) {
	$options = get_option('wp_cos');
	$options = unserialize($options);
	if(!$options || !$options['domain'] || 'on' != $options['gravatar']) {
		return $url;
	}

	$url = preg_replace('/(?:http|https):\/\/\S+gravatar\.com\/avatar\/(\S+)/', $options['domain'] . '/gravatar/$1', $url);
	return $url;
}
add_filter('get_avatar_url', 'cos_get_avatar_url', 10, 1);
?>